#include "Buffer.h"

#include <errno.h>
#include <sys/uio.h>
#include <unistd.h>

ssize_t Buffer::readFd(int fd,int* saveErrno)
{
    /*
    iovec 是系统提供的结构体
    包含两个成员：iov_base（缓冲区起始地址）和 iov_len（缓冲区长度）
    用于 readv 实现分散读（一次系统调用写入多个缓冲区）
    */
    char extrabuf[65536]={0}; // 栈上的内存空间
    struct iovec vec[2];
    const size_t writable = writableBytes(); // buffer底层缓冲区剩余可写空间
    vec[0].iov_base=begin()+writerIndex_;
    vec[0].iov_len=writable;

    vec[1].iov_base=extrabuf;
    vec[1].iov_len=sizeof(extrabuf);

    const int iovcnt = (writable<sizeof extrabuf) ? 2 : 1;
    const ssize_t n = ::readv(fd,vec,iovcnt);
    if(n<0)
    {
        *saveErrno=errno;
    }
    else if(n<=writable) // Buffer的可写缓冲区已经够存储读出来的数据了
    {
        writerIndex_+=n;
    }
    else //extrabuf里也写入了数据
    {
        writerIndex_=buffer_.size();
        append(extrabuf,n-writable); //从writeIndex_开始写n-writable大小数据
    }

    return n;
}

ssize_t Buffer::writeFd(int fd,int* saveErrno)
{
    ssize_t n =::write(fd,peek(),readableBytes());
    if(n<0)
    {
        *saveErrno = errno;
    }
    return n;
}